import { useMemo, useRef } from 'react'
import { useMemoizedFn } from 'ahooks'
import _ from 'lodash'
import { message, Upload, UploadFile } from 'antd'

import { fileValidate } from '@/utils/utils'
import { CusUpload, TCusUploadProps } from './CusUpload'

const debounceShowErrMsg = _.debounce((msg: string) => void message.error(msg), 0)

export type TFile = { fileName: string; fileUrl: string; fileSize?: string | number }

/**
 * 附件上传
 * - 可能要结合 Form.Item 的 getValueProps、getValueFromEvent 这两个属性进行转换，具体请参考相关示例
 */
export const FormItemUpload = Object.assign(
  (
    props: Omit<TCusUploadProps, 'defaultFileList' | 'fileList' | 'onChange'> &
      Pick<Parameters<typeof fileValidate>[1], 'max'> & {
        /**
         * 缩略图按长边缩放（仅图片有效；不要随意变更缩放值，尽可能保持稳定）  非响应式属性
         * @default 100
         */
        ossResizeL?: number
        /** 外部自行通过key来重置初始回显 */
        value?: TFile[] | null
        onChange?: (value: TFile[]) => void
        onRowChange?: (value: any) => void
      },
  ) => {
    const { max, ossResizeL, value, onRowChange, ...cusUploadProps } = props
    const { maxCount, accept, beforeUpload, onChange } = cusUploadProps

    const list = value || []
    const objRef = useRef({ list, ossResizeL })
    const defaultList: UploadFile[] = useMemo(
      () =>
        objRef.current.list.map(({ fileName, fileUrl }, i) => {
          let thumbUrl
          if (fileUrl.includes('.aliyuncs.com/') && !/\?|#/.test(fileUrl) && fileValidate.isImgUrl(fileUrl)) {
            thumbUrl = `${fileUrl}?x-oss-process=image/resize,l_${objRef.current.ossResizeL || 100}`
          }
          return {
            uid: `${i}_${fileUrl}`,
            name: fileName,
            url: fileUrl,
            status: 'done',
            thumbUrl,
          }
        }),
      [],
    )

    const handleChange = useMemoizedFn<NonNullable<TCusUploadProps['onChange']>>(({ fileList }) => {
      const doneList = fileList.filter(f => f.status === 'done')
      onRowChange?.(doneList)
      const newList = doneList.map<TFile>(f => {
        const resp: any = (f as any).response || {}
        return {
          fileName: resp.fileName || (f as any).fileName || f.name,
          fileUrl: resp.fileUrl || resp.url || f.url || '',
          fileSize: ((f.size || 0) / 1024 / 1024).toFixed(4),
        }
      })
      if (!_.isEqual(newList, list)) onChange?.(newList)
    })

    const handleBeforeUpload = useMemoizedFn<NonNullable<TCusUploadProps['beforeUpload']>>((file, fileList) => {
      if (maxCount && maxCount !== 1 && list.length + fileList.length > maxCount) {
        debounceShowErrMsg(`最多只能上传${maxCount}个附件`)
        return FormItemUpload.LIST_IGNORE
      }
      const msg = fileValidate(fileList, { accept, max })
      if (msg) {
        debounceShowErrMsg(msg)
        return FormItemUpload.LIST_IGNORE
      }
      return beforeUpload?.(file, fileList)
    })

    return (
      <CusUpload
        {...cusUploadProps}
        defaultFileList={defaultList}
        fileList={undefined}
        beforeUpload={handleBeforeUpload}
        onChange={handleChange}
      />
    )
  },
  {
    /** 在 beforeUpload 中返回该值则停止上传，且列表中不展示 */
    LIST_IGNORE: Upload.LIST_IGNORE,
  },
)
